using System;
using System.Collections.Generic;
using System.Linq;
using Engine;
using Engine.OldSerialization;

namespace RuthlessConquest {
    public struct GameCreationParameters {
        public class Serializer : ISerializer<GameCreationParameters> {
            public void Serialize(InputArchive archive, ref GameCreationParameters value) {
                archive.Serialize("Seed", ref value.Seed);
                archive.Serialize("PlanetsCount", ref value.PlanetsCount);
                archive.Serialize("SpecialPlanetsCount", ref value.SpecialPlanetsCount);
                archive.Serialize("NeutralsPopulationFactor", ref value.NeutralsPopulationFactor);
                archive.Serialize("ShipRange", ref value.ShipRange);
                archive.Serialize("ShipSpeed", ref value.ShipSpeed);
                archive.Serialize("ShipRepelFactor", ref value.ShipRepelFactor);
                archive.Serialize("PlanetRepelFactor", ref value.PlanetRepelFactor);
                archive.Serialize("MaxHumanPlayersCount", ref value.MaxHumanPlayersCount);
                archive.Serialize("CountdownTicksCount", ref value.CountdownTicksCount);
                archive.Serialize("CreatingPlayerFaction", ref value.CreatingPlayerFaction);
                archive.Serialize("CreatingPlayerName", ref value.CreatingPlayerName);
                archive.Serialize("CreatingPlayerGuid", ref value.CreatingPlayerGuid);
                archive.Serialize("CreatingPlayerPlatform", ref value.CreatingPlayerPlatform);
                archive.Serialize("AILevel", ref value.AILevel);
                archive.Serialize("SpecialEventsPeriod", ref value.SpecialEventsPeriod);
                archive.Serialize("NoProductionSteps", ref value.NoProductionSteps);
                archive.Serialize("PlanetValue", ref value.PlanetValue);
                archive.Serialize("SatelliteValue", ref value.SatelliteValue);
                archive.Serialize("AliensFactors", ref value.AliensFactors);
                archive.Serialize("ReinforcementsFactors", ref value.ReinforcementsFactors);
                archive.Serialize("Factions", ref value.Factions);
            }

            public void Serialize(OutputArchive archive, GameCreationParameters value) {
                archive.Serialize("Seed", value.Seed);
                archive.Serialize("PlanetsCount", value.PlanetsCount);
                archive.Serialize("SpecialPlanetsCount", value.SpecialPlanetsCount);
                archive.Serialize("NeutralsPopulationFactor", value.NeutralsPopulationFactor);
                archive.Serialize("ShipRange", value.ShipRange);
                archive.Serialize("ShipSpeed", value.ShipSpeed);
                archive.Serialize("ShipRepelFactor", value.ShipRepelFactor);
                archive.Serialize("PlanetRepelFactor", value.PlanetRepelFactor);
                archive.Serialize("MaxHumanPlayersCount", value.MaxHumanPlayersCount);
                archive.Serialize("CountdownTicksCount", value.CountdownTicksCount);
                archive.Serialize("CreatingPlayerFaction", value.CreatingPlayerFaction);
                archive.Serialize("CreatingPlayerName", value.CreatingPlayerName);
                archive.Serialize("CreatingPlayerGuid", value.CreatingPlayerGuid);
                archive.Serialize("CreatingPlayerPlatform", value.CreatingPlayerPlatform);
                archive.Serialize("AILevel", value.AILevel);
                archive.Serialize("SpecialEventsPeriod", value.SpecialEventsPeriod);
                archive.Serialize("NoProductionSteps", value.NoProductionSteps);
                archive.Serialize("PlanetValue", value.PlanetValue);
                archive.Serialize("SatelliteValue", value.SatelliteValue);
                archive.Serialize("AliensFactors", value.AliensFactors);
                archive.Serialize("ReinforcementsFactors", value.ReinforcementsFactors);
                archive.Serialize("Factions", value.Factions);
            }
        }

        public int Seed;

        public int PlanetsCount;

        public int SpecialPlanetsCount;

        public int NeutralsPopulationFactor;

        public int ShipRange;

        public int ShipSpeed;

        public int ShipRepelFactor;

        public int PlanetRepelFactor;

        public int MaxHumanPlayersCount;

        public int CountdownTicksCount;

        public Faction CreatingPlayerFaction;

        public string CreatingPlayerName;

        public Guid CreatingPlayerGuid;

        public Platform CreatingPlayerPlatform;

        public PlayerType AILevel;

        public int SpecialEventsPeriod;

        public int NoProductionSteps;

        public int PlanetValue;

        public int SatelliteValue;

        public Point3 AliensFactors;

        public Point3 ReinforcementsFactors;

        public DynamicArray<Faction> Factions;

        public GameCreationParameters(int seed,
            int planetsCount,
            int specialPlanetsCount,
            int neutralsPopulationFactor,
            int specialEventsPeriod,
            int shipRange,
            int maxHumanPlayersCount,
            int totalPlayersCount,
            int warmupTime,
            Faction creatingPlayerFaction,
            string creatingPlayerName,
            Guid creatingPlayerGuid,
            Platform creatingPlayerPlatform,
            PlayerType aiLevel) {
            Seed = seed;
            PlanetsCount = planetsCount;
            SpecialPlanetsCount = specialPlanetsCount;
            NeutralsPopulationFactor = neutralsPopulationFactor;
            ShipRange = shipRange;
            ShipSpeed = 750;
            PlanetRepelFactor = 25;
            ShipRepelFactor = 15;
            MaxHumanPlayersCount = maxHumanPlayersCount;
            CountdownTicksCount = warmupTime * 60 / 30 + 1;
            CreatingPlayerFaction = creatingPlayerFaction;
            CreatingPlayerName = creatingPlayerName;
            CreatingPlayerGuid = creatingPlayerGuid;
            CreatingPlayerPlatform = creatingPlayerPlatform;
            AILevel = aiLevel;
            SpecialEventsPeriod = specialEventsPeriod;
            NoProductionSteps = 900;
            PlanetValue = 90;
            SatelliteValue = 60;
            AliensFactors = new Point3(80, 50, 0);
            ReinforcementsFactors = new Point3(-30, -30, 200);
            Factions = GenerateRandomFactions(seed, creatingPlayerFaction, totalPlayersCount);
        }

        public static int CalculateSeed(string s) {
            if (string.IsNullOrEmpty(s)) {
                return new Random().Int();
            }
            int num = 0;
            for (int i = 0; i < s.Length; i++) {
                num += (1171 * i + 997) * s[i];
            }
            return MathUtils.Hash(num);
        }

        public static DynamicArray<Faction> GenerateRandomFactions(int seed, Faction creatingPlayerFaction, int factionsCount) {
            DynamicArray<Faction> dynamicArray = new();
            Random random = new(MathUtils.Hash(seed));
            List<Faction> list = Enumerable.Range(0, 6).Cast<Faction>().ToList();
            if (creatingPlayerFaction != Faction.None) {
                list.Remove(creatingPlayerFaction);
                dynamicArray.Add(creatingPlayerFaction);
            }
            while (dynamicArray.Count < factionsCount) {
                Faction item = list[random.Int(list.Count)];
                list.Remove(item);
                dynamicArray.Add(item);
            }
            return dynamicArray;
        }
    }
}